<?php
// +----------------------------------------------------------------------
// | Function：微信小程序基础接口
// +----------------------------------------------------------------------
// | Copyright (c) 多享 2023
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: xiaochun <3204016924@qq.com>
// +----------------------------------------------------------------------
namespace yvhsse;

use \Exception;

class Applets
{

    private static $host = 'https://api.weixin.qq.com';


    /**
     * 获取openid信息
     * @param string $AppId     小程序appid
     * @param string $AppSecret 小程序Secret
     * @param string $jsCode    小程序登录时获取的code
     * @return array
     * @author: xiaochun <3204016924@qq.com>
     * @Date  ：2024-08-27 14:47\
     * @link  : https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-login/code2Session.html
     */
    public static function getOpenInfo(string $AppId, string $AppSecret, string $jsCode): array
    {
        try {
            $path = '/sns/jscode2session';
            $params = [
                'appid'      => $AppId,
                'secret'     => $AppSecret,
                'js_code'    => $jsCode,
                'grant_type' => 'authorization_code'
            ];
            $result = Http::staticRequest(self::$host, $path, 'GET', $params);
            if (!$result) {
                throw new Exception('获取openid失败', 1);
            }
            $result = json_decode($result, true);
            if (isset($result['errcode']) && $result['errcode'] != 0) {
                if (strpos($result['errmsg'], 'code been used') !== false) {
                    throw new Exception('该code已使用', 1);
                }
                throw new Exception($result['errmsg']);
            }
        } catch (\Exception $e) {
            DebugLog::record($e, '获取openid失败');
            $msg = '获取openid失败';
            if ($e->getCode() == 1) {
                $msg = $e->getMessage();
            }
            return ['code' => 0, 'msg' => $msg];
        }
        return ['code' => 1, 'msg' => '获取成功', 'data' => $result];
    }


    /**
     * 解析手机号
     * @param string $appid     小程序AppID
     * @param string $appSecret 小程序Secret
     * @param string $phoneCode 小程序手机号验证时的code
     * @return array
     * @author: xiaochun <3204016924@qq.com>
     * @Date  ：2024-08-28 10:59
     * @link  : https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-info/phone-number/getPhoneNumber.html
     */
    public static function getPhoneNumber(string $appid, string $appSecret, string $phoneCode): array
    {
        try {
            $path = '/wxa/business/getuserphonenumber';
            $accessTokenRes = self::getStableAccessToken($appid, $appSecret);
            if (!$accessTokenRes['code']) {
                throw new Exception($accessTokenRes['msg'], 1);
            }
            $accessToken = $accessTokenRes['data']['access_token'];
            $path .= '?access_token=' . $accessToken;
            $param = [
                'code' => $phoneCode
            ];
            $result = Http::staticRequest(self::$host, $path, 'POST', json_encode($param));
            // $result = '{"errcode":0,"errmsg":"ok","phone_info":{"phoneNumber":"17311277193","purePhoneNumber":"17311277193","countryCode":"86","watermark":{"timestamp":1724813627,"appid":"wxe161402c7872bfd5"}}}';
            if (!$result) {
                throw new Exception('解析失败', 1);
            }
            $result = json_decode($result, true);
            if ($result['errcode'] != 0) {
                throw new Exception($result['errmsg'] ?? '解析返回数据信息错误', 1);
            }
            if (!isset($result['phone_info'])) {
                throw new Exception('数据信息有误');
            }
            $result = $result['phone_info'];
        } catch (\Exception $e) {
            DebugLog::record($e, '解析手机号失败');
            $msg = '解析手机号失败';
            if ($e->getCode() == 1) {
                $msg = $e->getMessage();
            }
            return ['code' => 0, 'msg' => $msg];
        }
        return ['code' => 1, 'msg' => '获取成功', 'data' => $result];
    }

    /**
     * 获取accessToken
     * @param string $appid  小程序AppID
     * @param string $secret 小程序Secret
     * @return array
     * @author: xiaochun <3204016924@qq.com>
     * @Date  ：2023-04-26 09:46
     * @link  https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getAccessToken.html
     */
    public static function getAccessToken(string $appid, string $secret): array
    {
        try {
            if (!$appid) {
                throw new Exception('appid未配置', 1);
            }
            if (!$secret) {
                throw new Exception('secret未配置', 1);
            }
            $path = '/cgi-bin/token';
            $param = [
                'grant_type' => 'client_credential',
                'appid'      => $appid,
                'secret'     => $secret,
            ];
            $result = Http::staticRequest(self::$host, $path, 'GET', $param);
            $result = json_decode($result, true);
            if (!$result) {
                throw new Exception('获取AccessToken失败', 1);
            }
        } catch (\Exception $e) {
            DebugLog::record($e, '获取accessToken失败');
            $msg = '获取accessToken失败';
            if ($e->getCode() == 1) {
                $msg = $e->getMessage();
            }
            return ['code' => 0, 'msg' => $msg];
        }
        return ['code' => 1, 'msg' => '获取成功', 'data' => $result];
    }

    /**
     * 获取稳定版AccessToken
     * @param string $appid  小程序AppID
     * @param string $secret 小程序Secret
     * @return array
     * @author: xiaochun <3204016924@qq.com>
     * @Date  ：2023-06-29 16:57
     * @link  https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getStableAccessToken.html
     */
    public static function getStableAccessToken(string $appid, string $secret): array
    {
        try {
            if (!$appid) {
                throw new Exception('appid未配置', 1);
            }
            if (!$secret) {
                throw new Exception('secret未配置', 1);
            }
            $path = '/cgi-bin/stable_token';
            $param = [
                'grant_type' => 'client_credential',
                'appid'      => $appid,
                'secret'     => $secret,
            ];
            $result = Http::staticRequest(self::$host, $path, 'POST', json_encode($param));
            $result = json_decode($result, true);
            if (!$result) {
                throw new Exception('获取AccessToken失败', 1);
            }
        } catch (\Exception $e) {
            DebugLog::record($e, '获取accessToken失败');
            $msg = '获取accessToken失败';
            if ($e->getCode() == 1) {
                $msg = $e->getMessage();
            }
            return ['code' => 0, 'msg' => $msg];
        }
        return ['code' => 1, 'msg' => '获取成功', 'data' => $result];
    }

    /**
     * 获取不限量小程序码
     * @param string $accessToken 微信accessToken
     * @param string $scene       扩展参数,最大支持32个字符
     * @param string $page        访问页面路径
     * @param int    $width       二维码宽度,默认:430,最小值：280,最大值：1280
     * @param bool   $checkPath   验证页面是否存在，开发模式使用
     * @param bool   $isHyline    是否需要透明背景
     * @param string $envVersion  打开小程序版本
     * @return array
     * @author: xiaochun <3204016924@qq.com>
     * @Date  ：2023-04-26 10:02
     * @link  https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/qrcode-link/qr-code/getUnlimitedQRCode.html
     */
    public static function getUnLimitQrCode(string $accessToken, string $scene, string $page,
                                            string $envVersion = 'release', int $width = 430,
                                            bool   $isHyline = false, bool $checkPath = true): array
    {
        try {
            $path = '/wxa/getwxacodeunlimit?access_token=' . $accessToken;
            $param = [
                //最大32个可见字符，只支持数字，大小写英文以及部分特殊字符：!#$&'()*+,/:;=?@-._~，
                //其它字符请自行编码为合法字符（因不支持%，中文无法使用 urlencode 处理，请使用其他编码方式）
                'scene'       => $scene,
                'page'        => $page,
                'check_path'  => $checkPath,//是否验证页面存在,正式上线需要开启
                'width'       => $width,//默认430,最小280px,最大1280px
                'is_hyaline'  => $isHyline,//是否透明
                'env_version' => $envVersion,//正式版为 "release"，体验版为 "trial"，开发版为 "develop"。默认是正式版
            ];
            $param = json_encode($param, JSON_UNESCAPED_UNICODE);
            $result = Http::staticRequest(self::$host, $path, 'POST', $param);
            if (substr($result, 0, 1) == '{') {
                $result = json_decode($result, true);
                throw new Exception('获取小程序二维码失败:' . $result['errmsg'] ?? '', 1);
            }
        } catch (\Exception $e) {
            $msg = '获取失败';
            if ($e->getCode() == 1) {
                $msg = $e->getMessage();
            }
            return ['code' => 0, 'msg' => $msg];
        }
        return ['code' => 1, 'msg' => '获取成功', 'data' => ['image' => $result]];
    }


    /**
     * 获取小程序短链接
     * @param string $accessToken     微信accessToken
     * @param string $page            进入的小程序页面路径
     * @param string $query           小程序页面参数
     * @param int    $expireType      过期时间类型，0:失效时间，1:失效天数
     * @param string $expireTimeOrDay 失效时间戳或失效天数
     * @param string $envVersion      要打卡的小程序版本 正式版为 "release"，体验版为"trial"，开发版为"develop",仅在微信外打开时生效
     * @author: xiaochun <3204016924@qq.com>
     * @Date  ：2024-12-20 15:03
     */
    public static function createShortLink(string $accessToken, string $page, string $query,
                                           int    $expireType, string $expireTimeOrDay,
                                           string $envVersion = 'release'): array
    {
        try {
            $path = '/wxa/generate_urllink?access_token=' . $accessToken;
            if (stripos($page, '?') !== false) {
                throw new Exception('小程序页面路径不能带参数');
            }
            $param = [
                'path'        => $page,// 不能带query 参数
                'query'       => $query,//通过 URL Link 进入小程序时的query,最大1024个字符，只支持数字，大小写英文以及部分特殊字符：!#$&'()*+,/:;=?@-._~%
                'expire_type' => $expireType,//过期时间类型，0:失效时间，1:失效天数
                'env_version' => $envVersion,//正式版为 "release"，体验版为 "trial"，开发版为 "develop"。默认是正式版
            ];
            if ($envVersion != 'release') {
                unset($param['path']);
            }
            if ($expireType == 0) {
                if (!$expireTimeOrDay) {
                    throw new Exception('请传入过期时间');
                }
                if (is_string($expireTimeOrDay)) {
                    $param['expire_time'] = strtotime($expireTimeOrDay);
                } else {
                    $param['expire_time'] = $expireTimeOrDay;
                }
            } else {
                if (!$expireTimeOrDay) {
                    throw new Exception('请传入过期天数');
                }
                $param['expire_interval'] = $expireTimeOrDay;
            }
            $param = json_encode($param, JSON_UNESCAPED_UNICODE);
            $result = Http::staticRequest(self::$host, $path, 'POST', $param);
            $result = json_decode($result, true);
            if ($result['errcode'] != 0) {
                throw new Exception($result['errmsg'] ?? '获取链接失败');
            }
            $result = [
                'url_link' => $result['url_link'],
            ];
        } catch (\Exception $e) {
            $msg = '获取失败';
            if ($e->getCode() == 1) {
                $msg = $e->getMessage();
            }
            return ['code' => 0, 'msg' => $msg];
        }
        return ['code' => 1, 'msg' => '获取成功', 'data' => $result];
    }

}